home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * canundo -
- * Support undo on canvases.
- *
- * Paul Haeberli - 1993
- *
- * exports
- *
- void freeundo(c)
- void addundo(c)
-
- void saverect(c,r)
- void undopaint(c)
- void clearundo(c)
- *
- */
- #include "stdio.h"
- #include "canvas.h"
- #include "chunkarena.h"
-
- unsigned long *chunkalloc();
-
- static chunkarena *undoarena;
-
- void freeundo(c)
- canvas *c;
- {
- undobuf *u;
- int n;
- unsigned long **lptr;
-
- u = c->undo;
- if(!u)
- return;
- n = u->xsize*u->ysize;
- lptr = u->data;
- while(n--) {
- if(*lptr)
- chunkfree(undoarena,*lptr);
- lptr++;
- }
- myfree(u->data);
- myfree(u);
- c->undo = 0;
- }
-
- void addundo(c)
- canvas *c;
- {
- undobuf *u;
-
- u = (undobuf*)mymalloc(sizeof(undobuf));
- u->xsize = ((c->xsize-1)/UNDOTILE)+1;
- u->ysize = ((c->ysize-1)/UNDOTILE)+1;
- u->data = (unsigned long **)mymalloc(u->xsize*u->ysize*sizeof(long*));
- bzero(u->data,u->xsize*u->ysize*sizeof(long*));
- c->undo = u;
- if(!undoarena)
- undoarena = newchunkalloc(UNDOTILE*UNDOTILE*sizeof(long));
- }
-
- static unsigned long *canvastile(c,tx,ty)
- canvas *c;
- int tx, ty;
- {
- unsigned long *dptr, *sptr, *ret;
- int iy, cx, cy, nx, ny;
-
- ret = dptr = chunkalloc(undoarena);
- cx = UNDOTILE*tx;
- cy = UNDOTILE*ty;
- sptr = c->data+(cy*c->xsize+cx);
- if((cx+UNDOTILE)<=c->xsize && (cy+UNDOTILE)<=c->ysize) {
- for(iy=0; iy<UNDOTILE; iy++) {
- bcopy(sptr,dptr,UNDOTILE*sizeof(long));
- sptr += c->xsize;
- dptr += UNDOTILE;
- }
- } else {
- nx = c->xsize-cx;
- if(nx>UNDOTILE) nx = UNDOTILE;
- ny = c->ysize-cy;
- if(ny>UNDOTILE) ny = UNDOTILE;
- for(iy=0; iy<ny; iy++) {
- bcopy(sptr,dptr,nx*sizeof(long));
- sptr += c->xsize;
- dptr += UNDOTILE;
- }
- }
- return ret;
- }
-
- void saverect(c,r)
- canvas *c;
- rct *r;
- {
- undobuf *u;
- int tx, tx1, tx2;
- int ty, ty1, ty2;
- rct srct;
-
- u = c->undo;
- if(!u)
- return;
- if(!rctinter(&c->area,r,&srct))
- return;
- tx1 = srct.xmin/UNDOTILE;
- tx2 = srct.xmax/UNDOTILE;
- ty1 = srct.ymin/UNDOTILE;
- ty2 = srct.ymax/UNDOTILE;
- if(tx2>=u->xsize || ty2>=u->ysize) {
- fprintf(stderr,"Blody heck\n");
- return;
- }
- for(ty=ty1; ty<=ty2; ty++) {
- for(tx=tx1; tx<=tx2; tx++) {
- if(u->data[ty*u->xsize+tx] == 0)
- u->data[ty*u->xsize+tx] = canvastile(c,tx,ty);
- }
- }
- }
-
- void undopaint(c)
- canvas *c;
- {
- undobuf *u;
- unsigned long *dptr, *sptr, *cantile;
- int iy, cx, cy, nx, ny;
- int tx, ty;
- rct r;
-
- u = c->undo;
- if(!u)
- return;
- for(ty=0; ty<u->ysize; ty++) {
- for(tx=0; tx<u->xsize; tx++) {
- sptr = u->data[ty*u->xsize+tx];
- if(sptr) {
- r.xmin = (tx+0)*UNDOTILE;
- r.xmax = (tx+1)*UNDOTILE;
- r.ymin = (ty+0)*UNDOTILE;
- r.ymax = (ty+1)*UNDOTILE;
- markdirty(c,&r,1);
- cantile = canvastile(c,tx,ty);
- cx = UNDOTILE*tx;
- cy = UNDOTILE*ty;
- dptr = c->data+(cy*c->xsize+cx);
- if((cx+UNDOTILE)<=c->xsize && (cy+UNDOTILE)<=c->ysize) {
- for(iy=0; iy<UNDOTILE; iy++) {
- bcopy(sptr,dptr,UNDOTILE*sizeof(long));
- dptr += c->xsize;
- sptr += UNDOTILE;
- }
- } else {
- nx = c->xsize-cx;
- if(nx>UNDOTILE) nx = UNDOTILE;
- ny = c->ysize-cy;
- if(ny>UNDOTILE) ny = UNDOTILE;
- for(iy=0; iy<ny; iy++) {
- bcopy(sptr,dptr,nx*sizeof(long));
- dptr += c->xsize;
- sptr += UNDOTILE;
- }
- }
- chunkfree(undoarena,u->data[ty*u->xsize+tx]);
- u->data[ty*u->xsize+tx] = cantile;
- }
- }
- }
- flushcanvas(c);
- }
-
- void clearundo(c)
- canvas *c;
- {
- undobuf *u;
- int tx, ty;
-
- u = c->undo;
- if(!u)
- return;
- for(ty=0; ty<u->ysize; ty++) {
- for(tx=0; tx<u->xsize; tx++) {
- if(u->data[ty*u->xsize+tx]) {
- chunkfree(undoarena,u->data[ty*u->xsize+tx]);
- u->data[ty*u->xsize+tx] = 0;
- }
- }
- }
- }
-